/*
 * 使用例子
 * 
 class BuffState {
    EventReg eventReg;
    public BuffState(EventMgr eventMgr)
    {
        eventReg = new EventReg(eventMgr);
        eventReg.Register(EventType.Damage, this::cb);
        eventReg.Register(EventType.Damage, (Integer data) -> {
        
        });
    }
    public void Destroy()
    {
        eventReg.Destroy();
    }
    void cb(Integer data)
    {
        Log.LDEBUG("BuffState cb");
    }
}

其他系统某些地方触发事件
eventMgr.FireEvent(EventType.Damage, 123);
 */
package com;
import java.util.ArrayList;
import java.util.function.Consumer;

public class EventSystem {
    public enum EventType 
    {   // 根据新项目继续增加 事件
        Damage,
        Heal,
        GetAddHp,
        MaxNum
    }
    // 一般一种事件就可以了，复杂系统，比如角色内部一套事件系统，场景外一套事件系统，就用2套或者改多套。
    public enum EventType2
    {
        S1,
        MaxNum
    }

    // 事件管理器
    public static class EventMgr {

        @SuppressWarnings("unchecked")
        private final ArrayList<Object>[] eventListeners = new ArrayList[Math.max(EventType.MaxNum.ordinal(), EventType2.MaxNum.ordinal())];
        private boolean isFiring = false; // 新增：标志位，表示是否正在触发事件
        // 注册事件
        <T> void Register(int eventId, EventListener<T> listener) {
            if (eventListeners[eventId] == null) {
                eventListeners[eventId] = new ArrayList<Object>();
            }
            eventListeners[eventId].add(listener);
        }

        //注销 所有属于eventReg 和 event
        void Unregister(int eventId, EventReg eventReg) {
            if (eventListeners[eventId] != null) {
                eventListeners[eventId].removeIf(l -> ((EventListener<?>) l).owner == eventReg);
            }
        }

        // 触发事件
        @SuppressWarnings("unchecked")
        public <T> void FireEvent(EventType type, T eventData) {
            if (isFiring) {
                throw new IllegalStateException("Recursive call to FireEvent is not allowed");
            }
            isFiring = true;
            try {
                int eventId = type.ordinal();
                if (eventListeners[eventId] == null) {
                    return;
                }

                // 复制callback列表 ,避免回调过程注册，注销导致异常
                ArrayList<Consumer<T>> callbacks = new ArrayList<>();
                for (Object listener : eventListeners[eventId]) {
                    callbacks.add(((EventListener<T>) listener).callback);
                }
                for (Consumer<T> callback : callbacks) {
                    callback.accept(eventData);
                }
            } finally {
                isFiring = false;
            }
        }

        public <T> void FireEvent(EventType2 type, T eventData) {
            if (isFiring) {
                throw new IllegalStateException("Recursive call to FireEvent is not allowed");
            }
            isFiring = true;
            try {
                int eventId = type.ordinal();
                if (eventListeners[eventId] == null) {
                    return;
                }

                // 复制callback列表 ,避免回调过程注册，注销导致异常
                ArrayList<Consumer<T>> callbacks = new ArrayList<>();
                for (Object listener : eventListeners[eventId]) {
                    callbacks.add(((EventListener<T>) listener).callback);
                }
                for (Consumer<T> callback : callbacks) {
                    callback.accept(eventData);
                }
            } finally {
                isFiring = false;
            }
        }
    }


    static class EventListener<T> {
        public Consumer<T> callback;
        public Object owner;

        public EventListener(Consumer<T> callback, Object owner) {
            this.callback = callback;
            this.owner = owner;
        }
    }

    // 事件注册器
    public static class EventReg {
        private final EventMgr eventMgr;
        private final ArrayList<Integer> registeredEvents = new ArrayList<Integer>(); //记录注册的事件，注销不删除
        public EventReg(EventMgr eventMgr) {
            this.eventMgr = eventMgr;
        }

        // 注册事件, 多次注册就多次回调
        public <T> void Register(EventType type, Consumer<T> callback) {
            eventMgr.Register(type.ordinal(), new EventListener<>(callback, this));
            registeredEvents.add(type.ordinal());
        }

        // 注销事件
        public void Unregister(EventType type) {
            eventMgr.Unregister(type.ordinal(), this);
        }

        // 注销所有事件
        public void Destroy() {
            for (int id : registeredEvents) {
                eventMgr.Unregister(id, this);
            }
        }
    }
}

